﻿//#define _CRT_SECURE_NO_WARNINGS
//#include <stdio.h>
//#include <string.h>
//#include <stdlib.h>
// C/C++ 学习网站：https://legacy.cplusplus.com 注意旧版本（搜索）和新版本

#include "common.h"

static void allocation_arr(char* pc)
{ // 申请内存空间，注意 pc 是临时拷贝指针
	pc = (char*)malloc(100);// 申请100字节的内存空间
	// 这里没有返回或释放 pc 必然导致内存泄漏，而且 pc 改变了指向，不会改变传入的指针的解引用值
}

static void allocation_ok(char** ppc)
{
	*ppc = (char*)malloc(100); // 解引用 ppc 得到传入指针地址，然后再申请100字节的内存空间
}

static void copy_str(void)
{
	char* copy = NULL;
	/*allocation_arr(copy); // pc 是 copy 的临时拷贝指针
	strcpy(copy, "Hello World"); // 这里的 copy 依然为 NULL，strcpy内部解引用会导致崩溃 */
	allocation_ok(&copy); // 正确的申请内存空间方式
	strcpy(copy, "Hello World"); // 正确的拷贝字符串
	printf("Copied string: %s\n", copy);
	free(copy);
	copy = NULL; // 释放内存空间
}

void test_problem()
{
	copy_str();
	printf("Test problem done.\n");
}

static size_t max_divisor(size_t n, size_t m)
{ // 返回最大公约数，使用辗转相除法
	if (!n || !m)
		return 0;
	else if (1 == n || 1 == m)
		return 1;
	else if (n == m)
		return n;
	while (m)
	{
		int temp = n % m;
		n = m;
		m = temp;
	}
	return n;
}

static size_t min_multiple(size_t n, size_t m)
{ // 返回最小公倍数
	if (!m || !n)
		return 0;
	else if (1 == n)
		return m;
	else if (1 == m)
		return n;
	else if (n == m)
		return n;
	int i = 2, n_copy = n;
	while (n && m && n_copy % m)
		n_copy = n * i++;
	return n_copy;
}

size_t sum_div_mul(size_t n, size_t m)
{ // 返回 n 和 m 的最大公约数和最小公倍数的和
	//return max_divisor(n, m) + min_multiple(n, m);
	size_t max_div = max_divisor(n, m);
	return  (n * m) / max_div + max_div; // 最小公倍数 = 两数乘积 / 最大公约数
}

void printf_square(int num)
{ // 打印一个 num 行的空心正方形
	int i, j;
	for (i = 1; i <= num; i++)
	{
		for (j = 1; j <= num; j++)
			if (i == 1 || i == num || j == 1 || j == num)
				printf("* ");
			else
				printf("  ");
		printf("\n");
	}
}

